﻿using System;
using System.ServiceModel;
using OnlineGameLibrary.Contract;
using OnlineGameLibrary.Game;
using System.ServiceModel.Channels;
using System.Diagnostics;

namespace OnlineGameClient.Service
{
    [CallbackBehavior(UseSynchronizationContext = false)]
    public class GameServiceClientProxy : IGameRoomServiceCallBack,IPlayerDuplexChannel
    {
        public IGameRoomService GameService
        {
            private set;
            get;
        }

        public GameServiceClientProxy()
        {
            GameService = CreateChannel();
        }

        IGameRoomService CreateChannel()
        {
            //var channelfactory = new DuplexChannelFactory<IGameRoomService>
            //    (new InstanceContext(this), "GameRoomService_endpint1");

            var channelfactory = new DuplexChannelFactory<IGameRoomService>
            (new InstanceContext(this), new PollingDuplexHttpBinding
            {
                ReceiveTimeout = TimeSpan.FromHours(1)
            });

            channelfactory.Endpoint.Behaviors.Add(
                new ReceiveTimeoutNotifyBehavior(TimeSpan.FromSeconds(50), HeartBeat));

            //"http://net4.xhinker.com/SLApp/Mog/Gameservice.svc/http"
            var channel = channelfactory.CreateChannel(new EndpointAddress("http://localhost/OnlineGamePlatform.Web/Gameservice.svc/http"));

            var basechannel = channel as ICommunicationObject;
            basechannel.Faulted += new EventHandler(basechannel_Faulted);
            basechannel.Closed += new EventHandler(basechannel_Closed);
            return channel;
        }

        // send heartbeat here.
        void HeartBeat(int count)
        {
            GameService.BeginUserHeartBeat(
                new AsyncCallback((ar) =>
                {
                    GameService.EndUserHeartBeat(ar);
                }), null);
        }

        void basechannel_Closed(object sender, EventArgs e)
        {
            CreateChannel();
            if (ChannelClosed != null)
                ChannelClosed(this, e);
        }

        void basechannel_Faulted(object sender, EventArgs e)
        {
            Debug.WriteLine("channel failed.");
        }

        // callback
        public void SendGameMessage(Message msg)
        {
            try
            {
                if (MessageReceived != null)
                    MessageReceived.Invoke(this,
                        new MessageEventArgs
                        {
                            Message = msg,
                        });
            }
            catch
            {
                throw;
            }
        }

        public event EventHandler ChannelClosed;
        public event EventHandler<MessageEventArgs> MessageReceived;

        public void SendMessage(Message msg)
        {
            this.GameService.BeginSendMessageToGame(
                msg,
                new AsyncCallback((ar) =>
                    {
                        
                        try
                        {
                            this.GameService.EndSendMessageToGame(ar);
                        }
                        catch (Exception ex) //error
                        {
                            Debug.WriteLine("callback failed. " + ex);
                        }
                    }),
                    null);
        }
    }
}
